/*AC自动机 = Trie图 <-(优化)- Trie字典树 + KMP 
* 1.KMP
    next[]:在p[]中，以p[i]结尾的后缀，能够匹配的从1开始的非平凡前缀的最大长度
    平凡前缀:完全相等
    //求next的过程，s,p的下标均从1开始
    next[0] = next[1] = 0;
    for(i = 2, j = 0; i <= n; i++)
    {
        while(j && s[i] != p[j+1]) j = next[j];
        if(s[i] == p[j+1]) j++;
        next[i] = j;
    }

* 2.AC自动机:对Trie 每个点的next一定比自己层数低,所以可以层序遍历bfs
    //trie树在每个节点上保存字符串的前缀 
    cnt节点出现的次数
    next在trie的每个节点上记录与当前已匹配串后缀匹配长度最大的前缀，即匹配失败的回溯点
    she在h处匹配失效会指向he的h(h已匹配)
    while(hh <= tt)
    {
        t = q[hh++];
        for(i = 0; i < 26; i++)
            c = trie[t, i];
            j = next[t];
            while(j && !trie[j, i]) j = next[j];
            if(trie[j, i]) j = trie[j, i];
            next[c] = j;
    }
j
* 本题:
    模板题中f[i][j]:前i个字母当前走到了kmp中的第j个位置
    本题中f[i][j]:前i个字母当前走到了AC自动机中的第j个位置的所有操作方案中，最少修改的字母数量

*/ 

#define DEBUG
#pragma GCC optimize("O1,O2,O3,Ofast")
#pragma GCC optimize("no-stack-protector,unroll-loops,fast-math,inline")
#pragma GCC target("avx,avx2,fma")
#pragma GCC target("sse,sse2,sse3,sse4,sse4.1,sse4.2,ssse3")

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e6+10, M = 210, INF = 0x3f3f3f3f;

int n;
int trie[N][26], id[M], nxt[N], idx; 
// id[]:每个模式串的结束节点
char str[N];
int f[N];
// 每个节点的匹配次数
int q[N];

void insert(int x)
{
    int p = 0;
    for(int i = 0; str[i]; i++)
    {
        int t = str[i] - 'a';
        if(!trie[p][t]) trie[p][t] = ++idx; //节点不存在就新建
        p = trie[p][t]; //指向下一个字符
        f[p]++;
    }
    id[x] = p;
}

void build()
{
    int hh = 0, tt = -1;
    for(int i = 0; i < 26; i++)
        if(trie[0][i]) 
            q[++tt] = trie[0][i]; //存储所有根节点

    while(hh <= tt)
    {
        int t = q[hh++]; //匹配节点
         for(int i = 0; i < 26; i++)
        {
            /*
            int c = trie[t][i]; //当前字符的每一种情况
            if(!c) continue; //当前情况不存在  
            int j = nxt[t]; //当前已匹配串的最长相同后缀
            while(j && !trie[j][i]) j = nxt[j]; //找到回溯点
            if(trie[j][i]) j = trie[j][i]; //当前节点存在，指向已匹配位置的下一个位置
            nxt[c] = j; //保存回溯点
            q[++tt] = c;
            */

            //线性优化
            int c = trie[t][i]; //当前字符的每一种情况
            if(!c) trie[t][i] = trie[nxt[t]][i]; //如果当前情况不存在，则考虑跳转
            else{
                nxt[c] = trie[nxt[t]][i]; //nextval优化
                q[++tt] = c;
            }  
            
        } 
    }
    
}

void query()
{
    for(int i = idx - 1; i >= 0; i--)
        f[nxt[q[i]]] += f[q[i]]; // 节点的失配节点一定在当前节点的上方，所以是自底向上的信息合并
}       //q队列中的节点是按层序顺序排列的，从高到低

int main()
{

    #ifdef DEBUG
    freopen("./in.txt","r",stdin);
    #else
    ios::sync_with_stdio(false);   
	cin.tie(0);
    #endif

    int n; cin >> n;

    for(int i = 0; i < n; i++){
        cin >> str; insert(i);
    }
    
    build(); 

    query();

    for(int i = 0; i < n; i++)
        printf("%d\n", f[id[i]]);
    return 0;
}

